#ifndef xpack_instruction_time_stamp
#define xpack_instruction_time_stamp
#pragma push_macro("xuser")
#undef  xuser
#define xuser mixc::instruction_time_stamp::inc
#include"configure/platform.hpp"
#include"define/base_type.hpp"
#include"macro/xexport.hpp"

#if xuse_mixc_rtos
#include"extern/rtos/cpu.hpp"
#include"extern/rtos/trace.hpp"
#endif

#pragma pop_macro("xuser")

namespace mixc::instruction_time_stamp{
    inline u64 time_stamp(){
    #if xuse_mixc_rtos
        while(true){
            u32 tick_lsb    = inc::cpu::systick();
            u64 tick_msb    = inc::g_trace.tick.total();

            // 放到 tick_msb 后边，确保在读取 tick_msb 时没有重新计数
            u32 tick_lsbx   = inc::cpu::systick();

            // 由于 tick_lsb 在计满数时会变成 0，类似于读取日期时，如果单独读取时分秒，每次读取的都是新的值
            // 当读取分钟的时候，时间是 01:59:59，但读取秒钟时变成 02:00:00，这样最后读到的值就变成了 01:59:00 时间就不正确
            // 这里也有类似的问题
            // 
            // 注意：
            // 这里关中断对内核定时器可能不起作用，所以这里使用循环检测的方式，一般最多就出现一次误差
            if (tick_lsbx < tick_lsb){
                continue;
            }
            else{
                u64 value   = tick_msb << inc::cpu::systick_bits() | tick_lsb;
                return value;
            }
        }
    #else
        #if xis_msvc_native
            extern u64 rdtsc();
            return rdtsc();
        #elif xis_x86
            return __builtin_ia32_rdtsc();
        #endif
    #endif
    }
}

#endif

xexport(mixc::instruction_time_stamp::time_stamp)